package com.cheetah.start.common.shoesImg;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgproc.Moments;

public class BackgroundAgnosticComparison {

    /**
     * 综合特征对比（推荐使用）
     */
    public static double compareShoesRobust(Mat shoe1, Mat shoe2) {
        // 提取多种背景无关特征
        Mat hist1 = BackgroundAgnosticFeature.extractRobustColorHistogram(shoe1);
        Mat hist2 = BackgroundAgnosticFeature.extractRobustColorHistogram(shoe2);

        Mat texture1 = BackgroundAgnosticFeature.extractTextureFeatures(shoe1);
        Mat texture2 = BackgroundAgnosticFeature.extractTextureFeatures(shoe2);

        Mat shape1 = extractShapeFeatures(shoe1);
        Mat shape2 = extractShapeFeatures(shoe2);

        // 计算各个特征的相似度
        double colorSimilarity = Imgproc.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL);
        double textureSimilarity = Imgproc.compareHist(texture1, texture2, Imgproc.CV_COMP_CORREL);
        double shapeSimilarity = computeCosineSimilarity(shape1, shape2);

        // 加权综合评分
        double finalScore = colorSimilarity * 0.5 + textureSimilarity * 0.3 + shapeSimilarity * 0.2;

        return Math.max(0, finalScore); // 确保非负
    }

    /**
     * 提取形状特征
     */
    private static Mat extractShapeFeatures(Mat image) {
        Mat shoeOnly = ContourBasedExtraction.extractShoeByContour(image);
        Mat gray = new Mat();
        Imgproc.cvtColor(shoeOnly, gray, Imgproc.COLOR_BGR2GRAY);

        // 计算Hu矩（形状描述符）
        Moments moments = Imgproc.moments(gray);
        Mat huMoments = new Mat();
        Imgproc.HuMoments(moments, huMoments);

        // 对数变换增强小值
        for (int i = 0; i < huMoments.rows(); i++) {
            double value = huMoments.get(i, 0)[0];
            huMoments.put(i, 0, -1 * Math.signum(value) * Math.log10(Math.abs(value)));
        }

        return huMoments;
    }

    private static double computeCosineSimilarity(Mat v1, Mat v2) {
        double dotProduct = v1.dot(v2);
        double norm1 = Core.norm(v1, Core.NORM_L2);
        double norm2 = Core.norm(v2, Core.NORM_L2);

        if (norm1 == 0 || norm2 == 0) return 0;
        return dotProduct / (norm1 * norm2);
    }
}
